home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
EnigmA Amiga Run 1996 June
/
EnigmA AMIGA RUN 08 (1996)(G.R. Edizioni)(IT)[!][issue 1996-06][EARSAN CD VII].iso
/
earcd
/
utmisc1
/
fscode.lha
/
Src
/
Decode.c
< prev
next >
Wrap
C/C++ Source or Header
|
1995-05-22
|
6KB
|
310 lines
/*
** $VER: Decode.c (22.5.95) by Flavio Stanchina
*/
#include <exec/types.h>
#include <dos/dos.h>
#include <dos/stdio.h>
#include <clib/exec_protos.h>
#include <clib/utility_protos.h>
#include <clib/dos_protos.h>
#include <ctype.h>
#include <string.h>
#if defined(__SASC)
#include <proto/exec.h>
#include <proto/utility.h>
#include <proto/dos.h>
#endif
#include "FSCode.h"
#include "CRC32.h"
BPTR OpenPart(struct FSData *fsd)
{
open_next:
/* For starters, open the input file when needed */
if (fsd->In == 0)
{
fsd->PhysPart += 1;
if (fsd->Multi)
SPrintf(fsd->Temp, NameFmt, fsd->File, fsd->PhysPart);
else
strcpy(fsd->Temp, fsd->File);
if (fsd->In = Open(fsd->Temp, MODE_OLDFILE))
{
SetVBuf(fsd->In, NULL, BUF_FULL, 16384);
}
else
{
if (!(fsd->Multi) || (fsd->PhysPart == 1))
MyPrintFault(fsd, IoErr(), fsd->Temp);
return 0;
}
}
/* Search a !start or !mstrt line */
while (FGets(fsd->In, fsd->Temp, sizeof(fsd->Temp)-1) != NULL)
{
STRPTR line = fsd->Temp + START_SKIP;
LONG part, parts;
/* !start, single-part file */
if (Strnicmp(fsd->Temp, StartFmt, START_SKIP) == 0)
{
if (fsd->Part != fsd->Parts)
{
FPuts(fsd->StdErr, "found a single-part header, was looking for a multi-part header\n");
return 0;
}
TrimLine(&line);
strcpy(fsd->Name, line);
fsd->Size = 0;
fsd->CRC = 0xFFFFFFFF; /* preload shift register, per CRC-32 spec */
fsd->NumFound += 1;
fsd->Part = fsd->Parts = 0;
}
/* !mstrt, multi-part file */
else if (Strnicmp(fsd->Temp, MultiFmt, START_SKIP) == 0)
{
part = GetDec(&line);
parts = GetDec(&line);
TrimLine(&line);
if (part > parts)
{
FPrintf(fsd->StdErr, "found part %ld/%ld", part, parts);
FPuts(fsd->StdErr, ", which is impossible\n");
return 0;
}
fsd->Part += 1;
if (fsd->Parts == 0)
{
strcpy(fsd->Name, line);
fsd->Size = 0;
fsd->CRC = 0xFFFFFFFF; /* preload shift register, per CRC-32 spec */
fsd->NumFound += 1;
fsd->Parts = parts;
}
else
{
if (Stricmp(fsd->Name, line) != 0)
{
FPrintf(fsd->StdErr, "found part %ld/%ld", part, parts);
FPrintf(fsd->StdErr, " of file \"%s\", was looking for file \"%s\"\n", line, fsd->Name);
return 0;
}
if ((part != fsd->Part) || (parts != fsd->Parts))
{
FPrintf(fsd->StdErr, "found part %ld/%ld", part, parts);
VFPrintf(fsd->StdErr, ", was looking for part %ld/%ld\n", &(fsd->Part));
return 0;
}
}
}
/* nothing, try again */
else continue;
fsd->BufPtr = fsd->Buffer;
fsd->BufCnt = 0;
return fsd->In;
}
/* If we get here, there wasn't a !start line in this file */
MyClose(fsd, fsd->In);
fsd->In = 0;
if (fsd->Multi)
goto open_next;
else return 0;
}
LONG FlushPart(struct FSData *fsd)
{
if (fsd->BufCnt)
{
/* Try and open specified file for output. */
if (fsd->Out == 0)
{
if ((fsd->Out = Open((fsd->To ? fsd->To : fsd->Name), MODE_NEWFILE)) == 0)
return -2;
}
/* Update size and CRC. */
fsd->Size += fsd->BufCnt;
fsd->CRC = CRC32_blocks(fsd->Buffer, fsd->BufCnt, fsd->CRC);
/* Write buffer to disk. */
fsd->BufPtr = fsd->Buffer;
if (Write(fsd->Out, fsd->BufPtr, fsd->BufCnt) != fsd->BufCnt) return -2;
fsd->BufCnt = 0;
if (CheckSignal(SIGBREAKF_CTRL_C)) return -3;
}
return 0;
}
/*
**
** RESULT
** 0 all ok
** -2 error from FlushPart()
** -4 error closing input file
*/
LONG ClosePart(struct FSData *fsd, LONG c)
{
LONG tmp;
if (tmp = FlushPart(fsd)) return tmp;
/* This should be a !end line. Make sure... */
if (c == '!')
{
fsd->Temp[0] = c;
if (FGets(fsd->In, fsd->Temp+1, sizeof(fsd->Temp)-2) != NULL)
{
if (Strnicmp(fsd->Temp, EndFmt, 5) == 0)
{
/* Check size and CRC against those saved in the !end line. */
TEXT *line = fsd->Temp+5;
fsd->RealSize = GetDec(&line);
fsd->RealCRC = GetHex(&line);
c = 0;
if (fsd->Size != fsd->RealSize) FPuts(fsd->StdErr, "size mismatch\n");
if (fsd->CRC != fsd->RealCRC ) FPuts(fsd->StdErr, "CRC mismatch\n");
}
}
}
/*
** This is getting complex. Close the output file if:
** - the user didn't specify an output file name;
** - the file is open;
** - we're at end of file (either single- or multi-part).
*/
if ((fsd->To == NULL) && (fsd->Out != 0) && (fsd->Part == fsd->Parts))
{
MyClose(fsd, fsd->Out);
fsd->Out = 0;
}
return c;
}
/***** Skip characters outside the ASCII 33-126 range *****/
#ifdef __SASC
__inline
#endif
static LONG MyGetC(struct FSData *fsd)
{
LONG c;
do {
if ((c = FGetC(fsd->In)) < 0) break;
} while((c < '!') || (c > '~'));
return c;
}
LONG Decode(struct FSData *fsd)
{
LONG c;
LONG len;
ULONG tmp;
while (1)
{
if (CheckSignal(SIGBREAKF_CTRL_C)) return -3;
len = 0;
tmp = 0;
/* 1 */
if ((c = MyGetC(fsd)) == ENDSTREAMCH) return -1;
if (c == '!')
{
if ((c = ClosePart(fsd, c)) != 0)
return c;
if (OpenPart(fsd))
continue;
else return 0;
}
if (c != '#')
{
tmp += c - 42;
tmp *= 85;
}
else len = 3;
/* 2 */
if ((c = MyGetC(fsd)) == ENDSTREAMCH) return -1;
if (c == '!') return c;
if (c != '#')
{
tmp += c - 42;
tmp *= 85;
}
else len = 2;
/* 3 */
if ((c = MyGetC(fsd)) == ENDSTREAMCH) return -1;
if (c == '!') return c;
if (c != '#')
{
tmp += c - 42;
tmp *= 85;
}
else len = 1;
/* 4 */
if ((c = MyGetC(fsd)) == ENDSTREAMCH) return -1;
if (c == '!') return c;
tmp += c - 42;
tmp *= 85;
/* 5 */
if ((c = MyGetC(fsd)) == ENDSTREAMCH) return -1;
if (c == '!') return c;
tmp += c - 42;
/* Put decoded data into output buffer, maybe flush buffer. */
switch(len)
{
case 3: fsd->BufPtr[2] = tmp; tmp >>= 8;
case 2: fsd->BufPtr[1] = tmp; tmp >>= 8;
case 1: fsd->BufPtr[0] = tmp;
fsd->BufPtr += len;
fsd->BufCnt += len;
/* Always flush buffer when it gets misaligned. */
if ((c = FlushPart(fsd)) != 0) return c;
break;
default:
*(LONG *)fsd->BufPtr = tmp;
fsd->BufPtr += 4;
fsd->BufCnt += 4;
/* Flush buffer if it gets close to overflow. */
if (fsd->BufCnt > FSD_BUFSIZ-4)
if ((c = FlushPart(fsd)) != 0) return c;
}
}
}